/**
 * C2-01: STM32F401CC
 * 	1. LED		PC13		低电平点亮
 * 	2. UART		PA9 PA10
 * 	3. I2C		PB8 PB9
 * A1-01: AT24C02
 * 	1. SCL		PB8
 * 	2. SDA		PB9
 * 	3. WP		PB0
 *
 * 设备地址需要观察主板上 A0 A1 A2 三个地址配置引脚上的电阻是接 GND 还是 VCC
 *    A2 A1 A0	7bit-device-address
 * 0.  0  0  0	0x50
 * 1.  0  0  0	0x51
 * 2.  0  0  0	0x52
 * 3.  0  0  0	0x53
 * 4.  0  0  0	0x54
 * 5.  0  0  0	0x55
 * 6.  0  0  0	0x56
 * 7.  0  0  0	0x57
 */

#include "stm32f4xx_hal.h"
#include <stdint.h>

extern uint32_t SystemCoreClock;
UART_HandleTypeDef huart1;
I2C_HandleTypeDef hi2c1;

void HAL_MspInit(void)
{
	__HAL_RCC_SYSCFG_CLK_ENABLE();
	__HAL_RCC_PWR_CLK_ENABLE();
}

void _board_error_handler(void)
{
	__disable_irq();
	while (1) {
	}
}

void _board_clock_init(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
	RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };

	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState = RCC_HSE_ON;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
	RCC_OscInitStruct.PLL.PLLM = 12;
	RCC_OscInitStruct.PLL.PLLN = 168;
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
	RCC_OscInitStruct.PLL.PLLQ = 4;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		_board_error_handler();
	}

	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
	    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
		_board_error_handler();
	}
}

void _board_uart_init()
{
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };

	/* UART CLK ENABLE */
	__HAL_RCC_USART1_CLK_ENABLE();

	/* UART IOREMAP */
	__HAL_RCC_GPIOA_CLK_ENABLE();
	GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	/* UART CONFIG */
	huart1.Instance = USART1;
	huart1.Init.BaudRate = 115200;
	huart1.Init.WordLength = UART_WORDLENGTH_8B;
	huart1.Init.StopBits = UART_STOPBITS_1;
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	if (HAL_UART_Init(&huart1) != HAL_OK) {
		_board_error_handler();
	}
}

void _board_i2c_init()
{
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };

	__HAL_RCC_GPIOB_CLK_ENABLE();

	GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = GPIO_PIN_0;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	__HAL_RCC_I2C1_CLK_ENABLE();

	hi2c1.Instance = I2C1;
	hi2c1.Init.ClockSpeed = 100000;
	hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
	hi2c1.Init.OwnAddress1 = 0;
	hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
	hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
	hi2c1.Init.OwnAddress2 = 0;
	hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
	hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
	HAL_I2C_Init(&hi2c1);
}

int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
	return (ch);
}

int board_i2c_read(uint8_t device_address, uint8_t* memory_address, uint8_t* buffer, uint32_t length)
{
	int ret = 0;
	int timeout = 1000;

	if (NULL == memory_address) {
		ret = HAL_I2C_Master_Receive(&hi2c1, device_address << 1, buffer, length, timeout);
	} else {
		ret = HAL_I2C_Mem_Read(&hi2c1, device_address << 1, *memory_address, I2C_MEMADD_SIZE_8BIT, buffer, length, timeout);
	}

	/* 访问成功延时5ms, 等待at24c02处理数据 */
	if (0 == ret) {
		HAL_Delay(5);
	}

	return ret;
}

int board_i2c_write(uint8_t device_address, uint8_t* memory_address, uint8_t* buffer, uint32_t length)
{
	int ret = 0;
	int timeout = 1000;

	if (NULL == memory_address) {
		ret = HAL_I2C_Master_Transmit(&hi2c1, device_address << 1, buffer, length, timeout);
	} else {
		ret = HAL_I2C_Mem_Write(&hi2c1, device_address << 1, *memory_address, I2C_MEMADD_SIZE_8BIT, buffer, length, timeout);
	}

	/* 访问成功延时5ms, 等待at24c02处理数据 */
	if (0 == ret) {
		HAL_Delay(5);
	}

	return ret;
}

void delay_ms(int ms)
{
	HAL_Delay(ms);
}

void board_init()
{
	/* STM32 HAL LIB */
	HAL_Init();

	/* SYSTEM CLK */
	_board_clock_init();

	/* External crystal oscillator: PH0 PH1 */
	__HAL_RCC_GPIOH_CLK_ENABLE();

	/* SWD Download: PA13 PA14 */
	__HAL_RCC_GPIOA_CLK_ENABLE();

	_board_uart_init();
	_board_i2c_init();
}
